package cloud.hedou.abp.message

import cloud.hedou.abp.remote.HttpClient
import cloud.hedou.abp.remote.HttpClient.Companion.create
import cloud.hedou.abp.remote.PagedList
import cloud.hedou.abp.starter.AbpContext
import cloud.hedou.abp.webcore.ForbiddenException
import org.springframework.retry.annotation.Backoff
import org.springframework.retry.annotation.Retryable
import org.springframework.scheduling.annotation.Async
import org.springframework.stereotype.Service
import retrofit2.HttpException

@Service
class RemoteMessageService(httpClient: HttpClient) {

    private val messageApi: MessageApi = httpClient.create()

    @Async
    @Retryable(
        maxAttempts = 100,
        backoff = Backoff(delay = 1000 * 60)
    )
    fun registerChannel(vararg channels: Channel) {
        val response = messageApi.createChannel(
            token = AbpContext.serverToken!!,
            payload = PagedList(channels.size, channels.toList())
        ).execute()
        if (!response.isSuccessful) {
            throw HttpException(response)
        }
    }

    /**
     * 通过远程服务发送系统消息给指定的用户。
     * @param tenantId String 租户
     * @param title String 消息标题
     * @param content String 消息内容
     * @param targetUserIdList List<String> 接收此消息的用户
     * @param severity Int 严重性
     * @param properties Map<String, Any>? 额外数据
     */
    fun sendMessage(
        channelName: String,
        tenantId: String,
        title: String,
        content: String,
        targetUserIdList: List<String>,
        severity: Int = 0,
        properties: Map<String, Any>? = null,
    ) {
        val call = messageApi.sendMessage(
            token = AbpContext.serverToken!!,
            payload = SentMessagePayload(
                channelName = channelName,
                severity = severity,
                data = MessageData(
                    title = title,
                    message = content,
                    properties = properties,
                ),
                userIds = targetUserIdList.distinct().map {
                    MessageReceiver(
                        tenantId = tenantId,
                        userId = it
                    )
                }
            )
        )
        val response = call.execute()
        if (!response.isSuccessful) {
            throw ForbiddenException("调用远程服务发送消息时发生了错误，请稍候重试。", HttpException(response))
        }
    }

}